package com.meicloud.license.appl.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.meicloud.license.appl.vo.LicenseRegisterDto;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.validation.constraints.NotBlank;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.Base64;

/**
 * AES加解密工具
 * 对称性加密，加解密的规则相同
 *
 * @author zhanghui145
 * @date 2022/1/11 9:56
 * @since 1.0.0
 */
@Component
public class AesUtils extends AbstractEncryptionUtils<LicenseRegisterDto> {

    @Override
    public String encrypt(LicenseRegisterDto registerDto,String rule) {
        try {
            // 获得密码类
            Cipher cipher = getCipherByMode(rule.getBytes(), Cipher.ENCRYPT_MODE);
            // 根据密码器的初始化方式--加密：将数据加密
            byte[] bytes = cipher.doFinal(getRegisterBytes(registerDto));
            // 将加密后的数据转换为字符串，返回
            return new String(Base64.getEncoder().encode(bytes), StandardCharsets.UTF_8);
        } catch (Exception ignored) {
            return null;
        }
    }

    @Override
    public String decrypt(@NotBlank String decoderCode, String rules) {
        try {
            // 获得密码
            Cipher cipher = getCipherByMode(rules.getBytes(), Cipher.DECRYPT_MODE);
            // 将加密并编码后的内容解码成字节数组
            byte[] byteContent = Base64.getDecoder().decode(decoderCode.getBytes(StandardCharsets.UTF_8));
            // 解密
            byte[] byteDecode = cipher.doFinal(byteContent);
            return new String(byteDecode, StandardCharsets.UTF_8);
        } catch (Exception e) {
            return null;
        }
    }

    private Cipher getCipherByMode(byte[] rules, final int mode)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        // 1.根据字节数组生成AES密钥
        SecretKeySpec key = new SecretKeySpec(rules, "AES");
        // 2.根据指定算法AES生成密码器
        Cipher cipher = Cipher.getInstance("AES");
        // 3.初始化密码器，第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作，第二个参数为使用的KEY
        cipher.init(mode, key);
        return cipher;
    }

    /**
     * 被加密明文
     *
     * @param register 注册信息
     * @return 明文bytes
     */
    private byte[] getRegisterBytes(LicenseRegisterDto register) {
        JSONObject object = JSONUtil.parseObj(register);
        object.putOnce("time", LocalDateTime.now().toString());
        return object.toString().getBytes(StandardCharsets.UTF_8);
    }
}
